const { SyncHook, SyncBailHook, AsyncSeriesHook, AsyncParallelHook } = require('tapable');

class Lesson {
  constructor() {
    // 注册hooks 容器
    this.hooks = {
      go: new SyncHook(['className']),
      level: new SyncBailHook(['level']),
      studentInfo: new AsyncParallelHook(['name', 'age']),
      today: new AsyncSeriesHook()
    }
  }

  tap() {
    // 往hooks 容器中添加事件/添加回调函数
    this.hooks.go.tap('goClass', (className) => {
      console.log(1111, className);
    })
    this.hooks.go.tap('goClass2', (className) => {
      console.log(222, className);
    })
    this.hooks.level.tap('getLevel', (level) => {
      console.log('level', level);
      return 222
    })
    this.hooks.level.tap('getLevel2', (level) => {
      console.log('level2', level);
    })
    // 异步钩子注册的一种方式
    this.hooks.studentInfo.tapAsync('studentInfo', (name, age, callback) => {
      setTimeout(() => {
        console.log('studentInfo', name, age);
        callback()
      }, 2000)
    })
    // 另一种异步钩子注册的方法
    this.hooks.studentInfo.tapPromise('studentInfoPromise', (name, age) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log('studentInfoPromise', name, age);
          resolve()
        }, 3000)
      })
    })
    this.hooks.today.tapAsync('today', (callback) => {
      setTimeout(() => {
        console.log('today');
        callback()
      }, 2000)
    })
    this.hooks.today.tapAsync('today2', (callback) => {
      setTimeout(() => {
        console.log('today2');
        callback()
      }, 3000)
    })
  }

  start() {
    // 使用hooks.go.call() 方法触发钩子
    this.hooks.go.call('hhh');
    this.hooks.level.call(1);
    // 异步钩子触发的方法 callAsync
    this.hooks.studentInfo.callAsync('mal', 18, () => {
      console.log('异步结束');
    })
    this.hooks.today.callAsync(() => {
      console.log('today异步结束');
    })
  }
}

const lesson = new Lesson();

lesson.tap();
lesson.start()
